<script>
import WithDialog from '@/components/WithDialog/withDialog'
import ProgrammeForm from './components/ProgrammeForm'
import CompanyForm from './components/CompanyForm.vue'
import { searchLocation, arrivalProgrammes, resolveCoordinate, createArrivalProgrammes, editArrivalProgrammes } from '@/api/v2/visitor.js'
import { atLeastN, get, atLeast } from '@/utils/kris_utils'
import dayjs from 'dayjs'
export default {
    components:{
        WithDialog,
        ProgrammeForm,
        CompanyForm
    },
    data(){
        return {
            id:null,
            loading:false,
            rawData:null,
            loadingStates:{
                submitting: false,
                loading:false
            },
            companyOverview: null,
            // companyOverview:{
            //     name:'宁波大榭开发区天正模具有限公司',
            //     contact:'+86 0574-86765788',
            //     workTime:'08:00-17:00',
            //     address:'宁波大榭开发区北渡路5号',
            //     location:{
            //         // 天正经纬度 121.939339,29.905345
            //         name:'宁波大榭开发区天正模具有限公司',
            //         latitude:29.905345,
            //         longitude:121.939339,
            //         scale:18
            //     }
            // },
            programmes:[],
            distances:new Map(),
            companyFormDiaog:{
                form: {
                    companyName: '',
                    contact: '',
                    workTime: null,
                    locationID: null,
                    address:''
                },
                title:'编辑公司地址信息',
                visible:false,
                confirm:() => {},
                cancel:() => this.companyFormDiaog.visible = false
            },
            programmeFormDiaog:{
                form: {
                    departureName: '',
                    departureID: null,
                    programme: ''
                },
                title:'',
                visible:false,
                confirm:() => {},
                cancel:() => this.programmeFormDiaog.visible = false
            },
            
            locationOptions:[],
            currentLocation:{
                latitude: null,
                longitude: null
            }
        }
    },
    computed:{
        logo(){
            const defaultCompanyLogo = this.$store.getters?.defaultCompany?.logo
            if(typeof defaultCompanyLogo === 'string' && defaultCompanyLogo.trim() !== '')
                return defaultCompanyLogo

            return null
        },
        actionsDisabled(){
            const arr = []

            if(this.loadingStates.loading || this.loadingStates.submitting){
                arr.push('SUBMIT', 'REFRESH', 'CREATE_PROGRAMME', 'EDIT_COMPANY')
            }

            return arr
        }
    },
    watch:{
        programmes(v){
            if(!this.companyOverview && !atLeast(this.companyOverview.location, ['latitude','longitude']))
                return
            
            if(!Array.isArray(v) || v.length <= 0)
                return

            this.distances.clear()

            for(let index in v){
                const item = v[index]
                this.getDistance(
                    this.companyOverview.location,
                    item.location
                )
                .then(distance => {
                    this.distances.set(index, distance)
                })
                .catch((e) => {
                    console.log(e)
                    this.distances.set(index, '暂无')
                })
            }
        }
    },
    methods:{
        distancesMap(index){
            return this.distances.get(index+'')
        },
        distanceFormatter(distance){
            return `${(distance / 1000).toFixed(1)} km`
        },
        calculateDistance(origin, destination) {
            const toRadians = (degrees) => {
                return degrees * Math.PI / 180;
            }

            let R = 6371000 // 地球半径，单位：米
            
            let lat1 = toRadians(origin.latitude);
            let lon1 = toRadians(origin.longitude);
            let lat2 = toRadians(destination.latitude);
            let lon2 = toRadians(destination.longitude);
            
            let deltaLat = lat2 - lat1;
            let deltaLon = lon2 - lon1;
            
            let a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
                    Math.cos(lat1) * Math.cos(lat2) *
                    Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2)
                    
            let c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
            
            let distance = R * c
            
            return distance
        },
        async getDistance(destination, origin, formatter = this.distanceFormatter){
            if(!atLeast(destination, ['latitude','longitude']))
                throw new Error('目的地经纬度不能为空')
                
            if(!atLeast(origin, ['latitude','longitude'])){
                // origin = await getCurrentLocation()
                throw new Error('起始地经纬度不能为空')
            }
            
            const distance = this.calculateDistance(origin, destination)
            if(typeof distance != 'number' && isNaN(distance))
                throw new Error('计算距离失败')
                
            if(typeof formatter === 'function')
                return formatter(distance)
                
            return distance
        },
        isActionDisabled(action){
            return this.actionsDisabled.includes(action)
        },
        parseCoordinate(coordinateStr){
            if(typeof coordinateStr !== 'string' && coordinateStr.trim() === '')
                return null

            let coordinate = coordinateStr.split(',')

            if(!atLeastN(coordinate, 2))
                return null

            return coordinate
            
        },
        async resolveCoordinate(coordinate){
            const data = {
                location: coordinate
            }
            
            const result = await resolveCoordinate(data)
            if(result.code !== 200 || result.data.status !== '1')
                throw new Error('获取经纬度信息失败')

            const coordinateParsed = this.parseCoordinate(coordinate)

            return {
                province: get(result.data,'regeocode.addressComponent.province', null),
                city: get(result.data,'regeocode.addressComponent.city', null),
                area: get(result.data,'regeocode.addressComponent.district', null),
                latitude:coordinateParsed[1],
                longitude:coordinateParsed[0],
                address: get(result.data,'regeocode.formatted_address', null),
                name: get(result.data,'regeocode.formatted_address', null)
            }
        },
        parseTimeRange(range){
            if(typeof range !== 'string' || range.trim() === '')
                return null

            const r = range.split('-')
            if(!atLeastN(r, 2))
                return null
        
            const d = `${dayjs().format('YYYY-MM-DD')} `

            return [dayjs(d+r[0]).toDate(), dayjs(d+r[1]).toDate()]
        },
        timeRangeFormatter(times, format = 'HH:mm'){
            if(!atLeastN(times, 2))
                return ''

            return `${dayjs(times[0]).format(format)}-${dayjs(times[1]).format(format)}`
        },
        async getArrivalProgrammes(){
            const params = {
                companyId: this.$store.getters.defaultCompany.id
            }

            const result = await arrivalProgrammes(params)
            if(result.code !== 200)
                throw new Error(data.message ?? '获取数据失败')

            this.rawData = result.data
            this.id = this.rawData.id
            this.companyOverview = {
                name: this.rawData.company_name,
                contact: this.rawData.contact,
                workTime: this.parseTimeRange(this.rawData.work_time),
                address: this.rawData.address,
                location: null
            }
            
            this.companyOverview.location = await this.resolveCoordinate(this.rawData.longitude_and_latitude)

            this.programmes = JSON.parse(this.rawData.programmes)
        },
        editCompany(){
            const isCreateMode = typeof this.id !== 'number' || isNaN(this.id)

            this.companyFormDiaog.confirm = async () => {
                await this.$refs['companyForm'].validate()

                const locationID = this.companyFormDiaog.form.locationID
                const targetLocation = this.locationOptions.find(item => item.id === locationID)
                let location = null
                if(targetLocation){
                    location = { ... targetLocation}
                    delete location['id']
                }
                
                this.companyOverview = {
                    name: this.companyFormDiaog.form.companyName,
                    workTime: this.companyFormDiaog.form.workTime,
                    contact: this.companyFormDiaog.form.contact,
                    address: this.companyFormDiaog.form.address,
                    location
                }

                this.companyFormDiaog.visible = false
            }
            this.companyFormDiaog.visible = true

            if(!isCreateMode){
                const locationID = this.generateHash(this.companyOverview.location)
                this.locationOptions = [ {...this.companyOverview.location, id:locationID } ]

                this.companyFormDiaog.form = {
                    companyName: this.companyOverview.name,
                    workTime: this.companyOverview.workTime,
                    contact: this.companyOverview.contact,
                    address: this.companyOverview.address, 
                    locationID
                }
            }
        },
        createProgramme(){
            this.programmeFormDiaog.title = '添加方案'
            this.programmeFormDiaog.cancel = () => {
                this.programmeFormDiaog.visible = false
                this.$refs['programmeForm'].resetFields()
            }
            this.programmeFormDiaog.confirm = async () => {
                try {
                    await this.$refs['programmeForm'].validate()
                    const { departureName, departureID, programme  } = this.programmeFormDiaog.form

                    const location = this.locationOptions.find(item => item.id === departureID)
                    if(location){
                        delete location['id']
                    }

                    this.programmes.push({
                        departureName,
                        programme,
                        location:{...location}
                    })
                    
                    this.$refs['programmeForm'].resetFields()
                    this.locationOptions = []
                    this.programmeFormDiaog.visible = false
                }catch(e){
                    console.log(e)
                }
            }
            this.programmeFormDiaog.visible = true
        },
        async deleteProgramme(index){
            await this.$confirm('您确定要删除这个方案吗?','提示')
            this.programmes.splice(index, 1)
        },
        editProgramme(index){
            const programme = this.programmes[index]
            if(!programme)return

            this.programmeFormDiaog.title = '编辑方案'
            this.programmeFormDiaog.cancel = () => {
                this.programmeFormDiaog.visible = false
                this.$refs['programmeForm'].resetFields()
            }
            this.programmeFormDiaog.confirm = async () => {
                try {
                    await this.$refs['programmeForm'].validate()

                    const { departureName, departureID, programme  } = this.programmeFormDiaog.form
                    const targetLocation = this.locationOptions.find(item => item.id === departureID)
                    let location = null
                    if(targetLocation){
                        location = {...targetLocation}
                        delete location['id']
                    }

                    this.programmes[index] = {
                        departureName,
                        programme,
                        location:{...location}
                    }

                    this.$refs['programmeForm'].resetFields()
                    this.locationOptions = []
                    this.programmeFormDiaog.visible = false
                }catch(e){
                    console.log(e)
                }
            }
            this.programmeFormDiaog.visible = true

            this.$nextTick(() => {
                const locationID = this.generateHash(programme.location)
                this.locationOptions = [ {...programme.location, id:locationID } ]
                this.programmeFormDiaog.form = {
                    departureID: locationID,
                    departureName: programme.departureName,
                    programme: programme.programme
                }
            })
        },
        async submit(){
            try {
                this.loadingStates.submitting = true
                const params = this.buildParams()
                const isCreateMode = typeof this.id !== 'number' || isNaN(this.id)
                
                if(isCreateMode){
                    const result = await createArrivalProgrammes(params)
                        .catch(e => {
                            throw new Error('创建到达计划失败')
                        })
                    
                    if(result.code !== 200)
                        throw new Error(result.message ?? '创建到达计划失败')
                    
                    console.log(result)
                    
                }else{
                    const result = await editArrivalProgrammes(params)
                        .catch(e => {
                            throw new Error('编辑到达计划失败')
                        })
                    
                    if(result.code !== 200)
                        throw new Error(result.message ?? '编辑到达计划失败')

                    console.log(result)
                }

                this.loadingStates.submitting = false
                this.$message.success('保存成功')
                this.refresh()
            }catch(e){
                this.loadingStates.submitting = false
            }

        },
        buildParams(){
            const isCreateMode = typeof this.id !== 'number' || isNaN(this.id)

            const params = {
                companyName: this.companyOverview.name,
                contact: this.companyOverview.contact,
                workTime: this.timeRangeFormatter(this.companyOverview.workTime),
                address: this.companyOverview.address,
                longitudeAndLatitude: `${this.companyOverview.location.longitude},${this.companyOverview.location.latitude}`,
                programmes: JSON.stringify(this.programmes)
            }

            if(!isCreateMode)
                params['id'] = this.id

            return params
        },
        generateHash(location) {
            const keyInfo = `${location.latitude},${location.longitude}-${location.address}`;
            let hash = 5381; 
            for (let i = 0; i < keyInfo.length; i++) {
                const char = keyInfo.charCodeAt(i)
                hash = ((hash << 5) + hash) + char
            }
            // 将结果转换为十六进制形式
            return hash.toString(16);
        },
        async fetchAddress(kw){
            if(!kw)return []

            const params = {
                keywords: kw
            }

            const result = await searchLocation(params)
            if(result.code !== 200)
                throw new Error('获取地址失败')

            if(!Array.isArray(result.data.pois))
                throw new Error('获取地址失败')

            this.locationOptions = result.data.pois.map(item => {
                const { id, pname, cityname, adname , address, name,location } = item
                const longitudeAndLatitude = location.split(',')
                return {
                    id,
                    province:pname,
                    city:cityname,
                    area:adname,
                    latitude:longitudeAndLatitude[1],
                    longitude:longitudeAndLatitude[0],
                    address,
                    name
                }
            })

        },
        beforeClose(callback){
            callback(true)
            this.$refs['programmeForm'].resetFields()
        },
        sleep(t){
            return new Promise(r => setTimeout(r,t))
        },
        async loadData(){
            const result = await Promise.allSettled([
                this.getArrivalProgrammes()
            ])
        },
        async refresh(){
            await this.initData()
        },
        async initData(){
            try {
                this.loadingStates.loading = true
                await Promise.allSettled([
                    this.loadData(),
                    this.sleep(300)
                ])
                this.loadingStates.loading = false
            }catch(e){
                this.loadingStates.loading = false
            }
        }
    },
    created(){
        window.abc = this
        this.initData()
    }
}
</script>

<template>
    <div class="app-container programme-container" v-loading="loadingStates.loading">
        <WithDialog 
            :title="companyFormDiaog.title" 
            :visible.sync="companyFormDiaog.visible"
            @confirm="companyFormDiaog.confirm"
            @cancel="companyFormDiaog.cancel"
        >
            <CompanyForm 
                ref="companyForm"
                v-model="companyFormDiaog.form" 
                :locationOptions="locationOptions" 
                :fetchAddressFn="fetchAddress" 
            />
        </WithDialog>

        <WithDialog 
            :title="programmeFormDiaog.title" 
            :visible.sync="programmeFormDiaog.visible"
            :beforeClose="beforeClose"
            @confirm="programmeFormDiaog.confirm"
            @cancel="programmeFormDiaog.cancel"
        >
            <ProgrammeForm 
                ref="programmeForm"
                v-model="programmeFormDiaog.form" 
                :locationOptions="locationOptions" 
                :fetchAddressFn="fetchAddress" 
            />
        </WithDialog>

        <el-row :gutter="20">
            <el-col :span="5">
                <div class="company-overview" style="height: 80vh;">
                    <template v-if="companyOverview">
                        <img v-if="logo" class="logo" :src="logo" />
                        <el-tooltip class="item" effect="dark" :content="companyOverview.name" placement="right">
                            <div class="name  company-text">{{ companyOverview.name }}</div>
                        </el-tooltip>
                        <div class="phone-container">
                            <svg-icon style="margin-right: 4px;" icon-class="phone" class="icon" />
                            <span>{{ companyOverview.contact }}</span>
                        </div>
                        <el-tag style="margin-top: 8px;" size="small" type="success">{{ timeRangeFormatter(companyOverview.workTime) }}</el-tag>
                        <el-tooltip class="item" effect="dark" :content="companyOverview.address" placement="right">
                            <div class="address company-text">{{ companyOverview.address }}</div>
                        </el-tooltip>
                    </template>
                    <div v-else class="empty">
                        <svg-icon icon-class="empty" style="font-size: 100px;" />
                        <div class="tips">暂无公司地址信息</div>
                    </div>
                    <div class="actions">
                        <el-button 
                            @click="editCompany" 
                            class="action" 
                            icon="el-icon-edit" 
                            type="text"
                            :disabled="isActionDisabled('EDIT_COMPANY')"
                        >
                            编辑
                        </el-button>
                    </div>
                </div>
            </el-col>

            <el-col :span="19">
                <div class="main" style="height: 80vh;overflow: hidden;">
                    <div class="header">
                        <el-button :loading="this.loadingStates.submitting" :disabled="isActionDisabled('SUBMIT')" @click="submit" size="mini" round>保存</el-button>
                        <el-button :disabled="isActionDisabled('REFRESH')" @click="refresh" size="mini" round>刷新</el-button>
                        <el-button :disabled="isActionDisabled('CREATE_PROGRAMME')" @click="createProgramme" size="mini" type="primary" round>添加方案</el-button>
                    </div>
                    <div class="programme-list" v-if="programmes.length > 0">
                        <div class="programme" v-for="(programme, index) in programmes">
                            <div class="body">
                                <div class="left">
                                    <div class="row departure-name">
                                        <div class="key">
                                            <svg-icon icon-class="train2" class="icon" />
                                        </div>
                                        <el-tooltip class="item" effect="dark" :content="programme.departureName" placement="bottom">
                                            <div class="value">{{ programme.departureName }}</div>
                                        </el-tooltip>
                                        
                                    </div>
                                    
                                    <div class="row departure">
                                        <div class="key">
                                            <svg-icon icon-class="location" class="icon" />
                                        </div>
                                        <div class="value">{{ programme.location.name }}</div>
                                    </div>
                                    
                                </div>
                                <div class="right" >
                                    <div class="go">
                                        <svg-icon icon-class="distance" class="icon" />
                                        <div class="label">{{ distancesMap(index) }}</div>
                                    </div>
                                </div>
                                <div class="actions" >
                                    <el-button class="action" icon="el-icon-edit" type="text" @click="editProgramme(index)" />
                                    <el-button class="action" icon="el-icon-delete" style="color: #f56c6c;" type="text" @click="deleteProgramme(index)" />
                                </div>
                            </div>
                            <div class="footer">
                                <div class="row programme">
                                    <div class="key">
                                        <svg-icon icon-class="guide2" class="icon" />
                                    </div>
                                    <el-tooltip class="item" effect="dark" :content="programme.programme" placement="bottom">
                                        <div class="value">{{ programme.programme }}</div>
                                    </el-tooltip>
                                    
                                </div>
                            </div>
                        </div>
                    </div>
                    <el-empty v-else description="暂无方案" />
                </div>
            </el-col>
        </el-row>
    </div>
</template>

<style lang="scss">
.programme-container {
    * {
        box-sizing: border-box;

    }
    .company-overview,.main {
        background-color: #fff;
        border-radius: 8px;
        padding: 12px;
        // box-shadow: 0 0 1rem 0.1rem rgba(0,0,0, 0.05);
    }
    .company-overview {
        display: flex;
        flex-direction: column;
        align-items: center;
        >.logo {
            width: 68px;
            height: 68px;
            border-radius: 50%;
        }

        >.name {
            font-size: 18px;
            margin-top: 1rem;
            font-weight: bold;
        }

        >.company-text{
            width: 100%;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            word-wrap: break-word;
        }
        >.phone-container {
            margin-top: 8px;
            color: #6e6e6e;
        }

        >.address {
            width: 84%;
            margin-top: 10px;
            font-size: 14px;
            background-color: #f0f0f0;
            padding: 6px 8px;
            border-radius: 6px;
            min-height: 80px;
            color: #8e8e8e;
        }

        >.empty {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-bottom: 20px;

            >.tips {
                font-size: 16px;
                color: #8e8e8e;
            }
        }
    }

    .main {
        display: flex;
        flex-direction: column;
        flex-wrap: nowrap;
        .header {
            padding: 8px 0;
            text-align: right;
        }
        .programme-list {
            flex-grow: 1;
            background-color: #f5f5f5;
            padding: 8px;
            border-radius: 8px;
            overflow: scroll;
            overflow-x: hidden;


            >.programme {
                border-radius: 8px;
                background-color: #fff;
                padding: 8px;
                display: inline-block;
                width: calc(calc(100% - 6px * 2 * 3) / 3);
                margin: 6px;

                &:hover {
                    >.body >.actions {
                        width: 1em;
                    }
                }

                .go {
                    display: flex;
                    flex-direction: column;
                    justify-content: center;
                    align-items: center;
                    height: 100%;
                    
                    >.icon {
                        width: 26px;
                        height: 26px;
                    }
                    
                    >.label {
                        color: #00000080;
                        font-size: 14px;
                        margin-top: 8px;
                    }
                }
                
                .row {
                    display: flex;
                    align-items: flex-start;
                    flex-wrap: nowrap;
                    color: #000000E5;
                    align-items: center;
                    
                    >.key {
                        display: flex;
                        align-items: center;
                        flex-wrap: nowrap;
                        margin-right: 10px;
                        >.icon {
                            font-size: 22px;
                        }
                    }
                    
                    &.departure-name {
                        margin-bottom: 10px;
                        .value {
                            color: #000000E5;
                            font-size: 18px;
                            font-weight: 700;
                            width: 140px;
                            overflow: hidden;
                            text-overflow: ellipsis;
                            white-space: nowrap;
                            word-wrap: break-word;
                        }
                    }
                    
                    &.departure {
                        margin-bottom: 12px;
                        .value {
                            color: #00000080;
                            font-size: 16px;
                        }
                    }
                    
                    &.programme {
                        color: #8e8e8e;
                        font-size: 14px;
                        margin-top: 8px;
                        align-items: flex-start;
                        
                        >.value {
                            overflow: hidden;
                            text-overflow: ellipsis;
                            display: -webkit-box;
                            -webkit-box-orient: vertical;
                            -webkit-line-clamp: 2;
                        }
                    }
                }
                
                >.body {
                    display: flex;
                    
                    >.left {
                        flex: 1;
                    }
                    
                    >.right {
                        padding: 0 19px;
                        border-left: 1px solid #DCDFE6FF;
                    }

                    >.actions {
                        width: 0;
                        overflow: hidden;
                        transition: width .3s;

                        >.action {
                            display: block;
                            margin-left: 0;
                        }
                    }
                }
            }
        }
    }
    
}
</style>